/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.util.ArrayList;

class Fastarepeat {
    public static long timeInUs() {
        return System.nanoTime();
    }
    // Modify n value to change the difficulty of the benchmark

    public int input = 250000;

    public int n = input;
    public static int width = 60;

    public static String aluString =
			"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" +
            "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" +
            "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" +
            "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" +
            "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" +
            "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" +
            "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
    public static int aluLen = aluString.length() - 1;
    public static int[] alu = new int[aluLen];
    public static void aluAddCode(){
        for (int i = 0; i < aluLen; i++) {
            alu[i] =  aluString.charAt(i);
        }
    }

    public static int repeatFasta(int geneLength, ArrayList<Integer> buffer, int[] gene2) {
        int pos = 0;
        int rpos = 0;
        int cnt = 500000;
        int lwidth = width;

        while (cnt > 0) {
            if (pos + lwidth > buffer.size()) {
                pos = 0;
            }
            if (rpos + lwidth > geneLength) {
                rpos = rpos % geneLength;
            }
            if (cnt < lwidth) {
                lwidth = cnt;
            }
            for (int i = 0; i < lwidth; i++) {
                buffer.set(pos + i, gene2[rpos + i]);
            }

            buffer.set(pos + lwidth, 10);
            pos += lwidth + 1;
            rpos += lwidth;
            cnt -= lwidth;
        }
        if (pos > 0 && pos < buffer.size()) {
            buffer.set(pos, 10);
        } else if (pos == buffer.size()) {
            buffer.set(0, 10);
        }

        int result = 0;
        for (int i = 0; i < buffer.size(); i++) {
            result += buffer.get(i);
        }
        return result;
    }
}
/*
 * @State
 * @Tags Jetstream2
 */
class Benchmark {
  public static void main(String[] args) {
      runFastaRepeat();
  }
  /*
   * @Benchmark
   */
  public static void runFastaRepeat() {
      int bufferSize = 256 * 1024;
      ArrayList<Integer> buffer = new ArrayList<>();
      for (int i = 0; i < bufferSize; i++) {
          buffer.add(10);
      }
      Fastarepeat.aluAddCode();
      int[] gene2 = new int[2 * Fastarepeat.aluLen];
      for (int i = 0; i < gene2.length; i++) {
          gene2[i] = Fastarepeat.alu[i % Fastarepeat.aluLen];
      }
      long res = 0;
      long start = Fastarepeat.timeInUs();
      for (int i = 0; i < 500; i++) {
          res += Fastarepeat.repeatFasta(Fastarepeat.aluLen, buffer, gene2);
      }
      long end = Fastarepeat.timeInUs();
      System.out.println("res: " + res);
      long time = (end - start);
      System.out.println("Array Access - RunFastaRepeat:" + time / 1_000_000.0 + "ms");
  }
}